"""
db.py 实现数据管理类和实体类基类
"""
import csv
import os
from typing import Union, Optional


class DataFile:
    """数据文件管理类"""

    def __init__(self, name: str, fieldnames: Union[list, tuple]):
        """
        初始化 DataFile 类对象

        :param name: 数据文件名
        :param fieldnames: 数据文件的字段名列表
        """
        # 构建文件路径
        self.file = os.path.join(os.path.dirname(__file__), name + '.csv')
        self.fieldnames = tuple(fieldnames)
        self.data = []
        self.load()  # 从文件加载数据

    def load(self):
        """
        从文件加载数据到内存
        """
        if not os.path.exists(self.file):
            open(self.file, 'w').close()
        with open(self.file, newline='', encoding='utf-8') as csvfile:
            self.data = [r for r in csv.DictReader(csvfile)]

    def save(self):
        """
        将内存中的数据保存到文件
        """
        with open(self.file, 'w', newline='', encoding='utf-8') as csvfile:
            writer = csv.DictWriter(csvfile, fieldnames=self.fieldnames)
            writer.writeheader()
            writer.writerows(self.data)

    def insert(self, **kwargs):
        """
        向数据文件中插入新的数据行

        :param kwargs: 插入的数据，以关键字参数形式传入
        """
        self.data.append(kwargs)
        self.save()

    def _select(self, condition: Optional[dict] = None) -> list:
        """
        根据条件查询数据

        :param condition: 查询条件，字典类型
        :return: 包含查询结果的列表，每个元素是一个包含行号和数据的列表
        """
        self.load()  # 确保数据一致
        result = []
        if condition is None or len(condition) == 0:
            result = [[r, self.data[r]] for r in range(len(self.data))]
        elif isinstance(condition, dict) and condition:
            row = 0
            for d in self.data:
                finded = True
                for k in condition.keys():
                    try:
                        if d[k] != condition[k]:
                            finded = False
                            break
                    except KeyError:
                        finded = False
                        break
                if finded:
                    result.append([row, d])
                row += 1
        return result

    def select(self, condition: Optional[dict] = None) -> list:
        """
        查询数据

        :param condition: 查询条件，字典类型
        :return: 包含查询结果的列表，每个元素是数据字典
        """
        return [d[1] for d in self._select(condition)]

    def update(self, condition: dict, **kwargs):
        """
        根据条件更新数据

        :param condition: 更新条件，字典类型
        :param kwargs: 更新的数据，以关键字参数形式传入
        """
        result = self._select(condition)
        for r in result:
            self.data[r[0]].update(kwargs)
        self.save()

    def delete(self, condition: dict):
        """
        根据条件删除数据

        :param condition: 删除条件，字典类型
        """
        if not isinstance(condition, dict):  # 避免整表删除
            return
        result = self._select(condition)
        row_list = [r[0] for r in result]
        row_list.sort(reverse=True)
        for r in row_list:
            self.data.pop(r)
        self.save()

    def clear(self):
        """
        清空数据文件中的所有数据
        """
        self.data.clear()
        self.save()


class BaseEntity:
    """
    实体类基类，提供所有实体类共有的基础方法
    """

    def __init__(self, file_name: str, header: Union[tuple, list]):
        self.header = header
        self.db = DataFile(file_name, self.header)

    def add_one(self, **kwargs):
        # 向数据库中添加一条记录
        self.db.insert(**kwargs)
        self.db.save()

    def delete(self, condition: dict):
        # 删除数据库中满足条件的记录
        self.db.delete(condition)
        self.db.save()

    def set(self, condition: dict, **kwargs):
        # 更新数据库中满足条件的记录
        self.db.update(condition, **kwargs)
        self.db.save()

    def get(self, condition: dict) -> list:
        # 返回满足条件的记录
        return self.db.select(condition)

    def get_all(self) -> list:
        # 返回数据库中的所有记录
        return self.db.select()

    def count(self, condition: Optional[dict] = None):
        # 返回满足条件的记录的数量
        return len(self.db.select(condition))
